package edu.cuit.canary;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executors;

/**
 * 接收来自浏览器的HTTP请求
 * 接收并解析HTTP请求
 * 创建并发送HTTP响应
 * @author <a href="mailto:1020zhaodan@163.com">Adan</a>
 * @version 1.0
 * @date 2025/8/2 9:15
 */
public class HttpServer {
    public static void main(String[] args) {
        try(var server = new ServerSocket(8848)){
            var executor = Executors.newVirtualThreadPerTaskExecutor();
            while(true){
                //监听客户端的连接
                var socket = server.accept();
                executor.execute(() -> service(socket));
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    /**
     * 服务器接收客户端的请求并响应
     * @param socket 客户端socket
     */
    public static void service(Socket socket) {
        try{
            System.out.println("客户端ip:" + socket.getInetAddress());
            //接收并解析HTTP请求
            var input = socket.getInputStream();
            /*
             * available():在读写操作前得知数据流中有多少个字节可以读取
             * 该方法用于网络数据读取时，容易出现错误：当使用available读取时，对方发送的数据可能还没有到达，得到的长度为0
             */
            var size = input.available();
            while(size == 0) size = input.available();
            var buffer = new byte[size];
            input.read(buffer);
            var requestHeader = new String(buffer);
            System.out.println(requestHeader);

            //解析HTTP请求
            var firstLineOfRequest = requestHeader.substring(0, requestHeader.indexOf("\r\n"));
            var uri = firstLineOfRequest.split(" ")[1];

            //决定http响应的正文类型
            String contentType;
            if(uri.indexOf(".html") != -1 || uri.indexOf(".htm") != -1)
                contentType = "text/html; charset=UTF-8";
            else if(uri.indexOf(".jpg") != -1 || uri.indexOf(".jpeg") != -1)
                contentType = "image/jpeg";
            else if(uri.indexOf(".gif") != -1)
                contentType = "image/gif";
            else
                contentType = "application/octet-stream";

            //根据url找到资源,同时读取资源并给客户端进行响应
            var path = "D:/workspace/cuit-046/javaweb-20250802/src/main/webapp" + uri;
            var file = new File(path);
            var output = socket.getOutputStream();

            //响应内容
            if(!file.exists()){
                //文件不存在，返回404
                output.write("HTTP/1.1 404 NOT FOUND\r\n".getBytes());
                output.write(("content-type: text/html; charset=UTF-8\r\n\r\n").getBytes());
                output.write("404,你所请求的资源不存在".getBytes());
            } else {
                output.write("HTTP/1.1 200 OK\r\n".getBytes());
                output.write((contentType + "\r\n\r\n").getBytes());
                var in = new BufferedInputStream(new FileInputStream(file));
                int len = -1;
                var buff = new byte[1024];
                while((len = in.read(buff)) != -1)
                    output.write(buff, 0, len);
                in.close();
            }
        }catch (IOException e){
            e.printStackTrace();
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
